# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------
"""
Software HEYU Team
------------------
- Website: http://www.heyu.org
- HEYU is used as base for development of scripts of piHAparsers
- Portions of piHAparsers scripts listed below have been derived from HEYU
  * piHAparsers/orelibs
  * piHAparsers/x10libs

Software MOCHAD Author
----------------------
- Website: http://sourceforge.net/apps/mediawiki/mochad/index.php?title=Main_Page
- MOCHAD is used as base for development of scripts of piHAparsers
- Portions of piHAparsers scripts listed below have been derived from MOCHAD
  * piHAparsers/x10libs
"""
# ----------------------------------------------------------------------------
# Use to convert hex string to x10 data
# For CM15a X10 RF events RX and TX
# ----------------------------------------------------------------------------

from .x10codes import *


def chkssec1(b):
   if (((b[0] ^ b[1]) != 0x0f) or ((b[2] ^ b[3]) != 0xff)):
       return False
   return True

def chkssec2(b):
   bitsum = 0
   for j in range(8):
       bitsum += (b[4] >> j) & 0x01
   e1 = (bitsum % 2)
   e2 = (b[5] & 0x80)
   if e1 & e2 == 0:
       return True
   else:
       if (not e1) and (not e2):
           return True
       return False


def fliphex(byte):
   """
   Convert a hex string 0xii (byte) by flipping byte[2] byte[3]
	0xbb -> 0x44
   """
   hexa = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
   flip = ['f','e','d','c','b','a','9','8','7','6','5','4','3','2','1','0']
   return '0x' + flip[hexa.index(byte[2])] + flip[hexa.index(byte[3])]


def chkx10rf(b):
   """
   Check an X10 b sequence of bytes integer
	[160, 95, 32, 223]
   """
   # Checksum 
   chks = b[2] ^ b[3]
   # check bytes b[1]  b[3]
   c1 = int(fliphex('0x%02x' % b[0]),base=16)
   c3 = int(fliphex('0x%02x' % b[2]),base=16)

   if (c3 != b[3]) or (c1 != b[1]) or (chks != 0xFF) :
       return False
   return True


def evalhuf1(data):
    """
    Convert an X10S  list of hex string
        ['0x45', '0x4a', '0x8c', '0x73', '0xae', '0x80']
    into human readable form
    """
    hu = data[0] + data[4][2:] + data[5][2:]
    f = SECmap[data[2]]
    return hu,f


def evalhuf2(data):
    """
    Convert an X10S  list of hex string
        ['0x45', '0x4a', '0x8c', '0x73', '0xae', '0x80']
    into human readable form
    hu addr : only 2 bytes
    """
    hu = data[0] + data[4][2:]
    f = SECmap[data[2]]
    return hu,f


# ----------------------------------------------------------------------------
# Use to convert seq b  to x10 data human readable
# For CM15a X10 RF standard events received RX
# ----------------------------------------------------------------------------

def cvh2x10rf(b):
    """
    Convert an X10 b sequence of bytes integer
        [160, 95, 32, 223]
	(or in hex string ['0xa0', '0x5f', '0x20', '0xdf'])
    into human readable form :  'G1' 'OFF'
    """
    # Function
    # b[2] -> f (string 0=ON, 1=OFF)
    funcint = (b[2] & (1<<5)) >> 5
    if funcint == 1:
        f = 'OFF'
    elif funcint == 0:
        f = 'ON'
    if b[2] == 0x98:
        f = 'DIM'
    elif b[2] == 0x88:
        f = 'BRIGHT'

    # Unit
    # b[0] -> u
    u = (b[0] & (1<<2)) << 1
    u |= (b[2] & (1<<6)) >> 4
    u |= (b[2] & (1<<3)) >> 2
    u |= (b[2] & (1<<4)) >> 4
    u = u + 1

    # House
    # b[0] -> h
    i = (b[0] & 0xf0) >> 4
    h = iHCrf[i]

    return [h.upper() + str(u),f]



# ----------------------------------------------------------------------------
# Use to convert x10 human readable data to seq integer
# For CM15a RF events transmitted TX
# ----------------------------------------------------------------------------

def x10rf2hex(args):
   """
   Convert an X10 command in human readable form:
	f : 'ON' or 'OFF'
	hu : house hu[0] + unit hu[1:] in string format
   into b = seq of 4 words in integer format for CM15a X10 RF Tx
   """
   hu,f,l = args
   b = [None,None,None,None]
   # Unit
   unit = int(hu[1:])-1
   unit8 = unit & 0x08
   unit4 = unit & 0x04
   unit2 = unit & 0x02
   unit1 = unit & 0x01
   # hu -> b[0]
   b[0] = (iHCrf.index(hu[0].lower()) << 4) | (unit8 >> 1)

   # Fonction
   # f -> b[2]
   f = f.upper()
   b[2] = 0
   if f == 'OFF':
       b[2] = 1 << 5
       b[2] |= (unit4 << 4) | (unit2 << 2) | (unit1 << 4)
   if f == 'ON':
       b[2] |= (unit4 << 4) | (unit2 << 2) | (unit1 << 4)
   if f == 'DIM':
       b[2] == 0x98
   if f == 'BRIGHT':
       b[2] == 0x88

   # Check bytes
   b[1] = int(fliphex('0x%02x' % b[0]),base=16)
   b[3] = int(fliphex('0x%02x' % b[2]),base=16)

   return ' '.join(['0x%02x' % i for i in b])



# ----------------------------------------------------------------------------
# ATI and X10 Remotes 
# ----------------------------------------------------------------------------


def chksrfr(b):
    return b[0] == ((b[2] << 4 ) +  (b[1] - 0x2b)) & 0xff

def atirmap(p):
    key = ('0x%02x' % p[0]) + ('%02x' % p[1])
    if key in ATIrmap:
        return 'NC',ATIrmap[key]
    return None

def pcrmap(p):
    if chksrfr(p):
        i = (p[2]>>4) & 0x0f
        if i < 16:
            hu = iHCrf[i]
        else:
            return None
        key = ('0x%02x' % p[1])
        if key in PCrmap:
            return hu,PCrmap[key]
    return None
